﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Text;
using System.Windows;
using NetBay.Core.BusinessEntities;
using NetBay.Core.BusinessEntities.Versioning;
using Rio.Framework.Localisation;
using Rio.Framework.Pages.Context;
using Telerik.Windows.Controls;

namespace Rio.Framework.Pages.Controls
{
    public partial class DocumentInformations
    {
        #region Enums
        private enum StateDoc
        {
            New = 0,
            Read,
            Indexed,
            Validated,
            Tranfered,
            Rejected,
            Done
        };

        #endregion

        #region Delegate

        public delegate void DocumentInformationHandler(object sender, DocumentInformationEventArgs args);

        #endregion

        #region Attributs

        private string m_sMsgIndexedBy;
        private string m_sMsgValidatedBy;
        private string m_sMsgTransferedBy;
        private string m_sMsgRejectedBy;
        private string m_sMsgReadBy;
        private string m_sLabelNoHistory;

        private readonly DelegateCommand _updateDocumentInformationCommand;

        private string _stateHisto;

        private string _authorLabel;
        private string _creditPhotoLabel;
        private string _noteLabel;
        private string _stateHistoLabel;
        private string _buttonUpdateLabel;
        private string _infoDocLabel;

        private FolderType _currentFolderType;

        public static readonly DependencyProperty DocumentProperty =
        DependencyProperty.Register("CurrentDocument", typeof(Document), typeof(DocumentInformations), new PropertyMetadata(OnDocumentChanged));

        public static readonly DependencyProperty CurrentVersionProperty =
        DependencyProperty.Register("CurrentVersion", typeof(VersioningItem), typeof(DocumentInformations), new PropertyMetadata(OnVersionChanged));

        public static readonly DependencyProperty AuthorProperty =
        DependencyProperty.Register("Author", typeof(string), typeof(DocumentInformations), null);

        public static readonly DependencyProperty NoteProperty =
        DependencyProperty.Register("Note", typeof(string), typeof(DocumentInformations), null);

        public static readonly DependencyProperty CreditPhotoProperty =
        DependencyProperty.Register("CreditPhoto", typeof(string), typeof(DocumentInformations), null);

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the author.
        /// </summary>
        /// <value>The author.</value>
        public string Author
        {
            get
            {
                return (string)GetValue(AuthorProperty);
            }
            set
            {
                SetValue(AuthorProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the credit photo.
        /// </summary>
        /// <value>The credit photo.</value>
        public string CreditPhoto
        {
            get
            {
                return (string)GetValue(CreditPhotoProperty);
            }
            set
            {
                SetValue(CreditPhotoProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the Note.
        /// </summary>
        /// <value>
        /// The Note.
        /// </value>
        public string Note
        {
            get
            {
                return (string)GetValue(NoteProperty);
            }
            set
            {
                SetValue(NoteProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the state histo.
        /// </summary>
        /// <value>The state histo.</value>
        public string StateHisto
        { 
            get
            {
                return _stateHisto;
            }
            set
            {
                _stateHisto = value;
                OnPropertyChanged("StateHisto");
            }
        }

        /// <summary>
        /// Gets or sets the author.
        /// </summary>
        /// <value>The author.</value>
        public string AuthorLabel
        { 
            get
            {
                return _authorLabel;
            }
            set
            {
                _authorLabel = value;
                OnPropertyChanged("AuthorLabel");
            }
        }

        /// <summary>
        /// Gets or sets the credit photo.
        /// </summary>
        /// <value>The credit photo.</value>
        public string CreditPhotoLabel
        { 
            get
            {
                return _creditPhotoLabel;
            }
            set
            {
                _creditPhotoLabel = value;
                OnPropertyChanged("CreditPhoto");
            }
        }

        /// <summary>
        /// Gets or sets the note label.
        /// </summary>
        /// <value>
        /// The note label.
        /// </value>
        public string NoteLabel
        { 
            get
            {
                return _noteLabel;
            }
            set
            {
                _noteLabel = value;
                OnPropertyChanged("NoteLabel");
            }
        }

        /// <summary>
        /// Gets or sets the state histo label.
        /// </summary>
        /// <value>The state histo.</value>
        public string StateHistoLabel
        { 
            get
            {
                return _stateHistoLabel;
            }
            set
            {
                _stateHistoLabel = value;
                OnPropertyChanged("StateHistoLabel");
            }
        }

        /// <summary>
        /// Gets or sets the info doc label.
        /// </summary>
        /// <value>The info doc label.</value>
        public string InfoDocLabel
        {
            get
            {
                return _infoDocLabel;
            }
            set
            {
                _infoDocLabel = value;
                OnPropertyChanged("InfoDocLabel");
            }
        }

        /// <summary>
        /// Gets or sets the button update label.
        /// </summary>
        /// <value>The button update label.</value>
        public string ButtonUpdateLabel
        {
            get
            {
                return _buttonUpdateLabel;
            }
            set
            {
                _buttonUpdateLabel = value;
                OnPropertyChanged("ButtonUpdateLabel");
            }
        }

        /// <summary>
        /// Gets or sets the type of the current folder.
        /// </summary>
        /// <value>The type of the current folder.</value>
        public FolderType CurrentFolderType
        {
            get
            {
                return _currentFolderType;
            }
            set
            {
                _currentFolderType = value;
                OnPropertyChanged("CurrentFolderType");
            }
        }

        /// <summary>
        /// Gets or sets the document.
        /// </summary>
        /// <value>The document.</value>
        public Document CurrentDocument
        {
            get
            {
                return (Document)GetValue(DocumentProperty);
            }
            set
            {
                SetValue(DocumentProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the current version.
        /// </summary>
        /// <value>The current version.</value>
        public VersioningItem CurrentVersion
        {
            get
            {
                return (VersioningItem)GetValue(CurrentVersionProperty);
            }
            set
            {
                SetValue(CurrentVersionProperty, value);
            }
        }

        /// <summary>
        /// Gets the update document information command.
        /// </summary>
        /// <value>The update document information command.</value>
        public DelegateCommand UpdateDocumentInformationCommand
        {
            get
            {
                return _updateDocumentInformationCommand;
            }
        }

        #endregion

        #region Events

        public event DocumentInformationHandler DocumentUpdating;
        private void RaiseDocumentUpdating()
        {
            if (DocumentUpdating != null)
                DocumentUpdating(this, new DocumentInformationEventArgs(Note, Author, CreditPhoto));
        }

        public event EventHandler DataLoaded;
        private void RaiseDataLoaded()
        {
            if (DataLoaded != null)
                DataLoaded(this, new EventArgs());
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="DocumentInformations"/> class.
        /// </summary>
        public DocumentInformations()
        {
            InitializeComponent();

            InitLabel();

            Author = string.Empty;
            Note = string.Empty;
            CreditPhoto = string.Empty;
            StateHisto = string.Empty;

            _updateDocumentInformationCommand = new DelegateCommand(OnUpdateInformation);
        }

        #endregion

        #region Functions

        /// <summary>
        /// Called when [document changed].
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs" /> instance containing the event data.</param>
        public static void OnDocumentChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            DocumentInformations context = source as DocumentInformations;
            if (context != null) context.InitializeDocumentInformations();
        }

        /// <summary>
        /// Called when [version changed].
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs" /> instance containing the event data.</param>
        public static void OnVersionChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            DocumentInformations context = source as DocumentInformations;
            if (context != null) context.InitializeVersionInformations();
        }

        /// <summary>
        /// Clears the informations.
        /// </summary>
        public void ClearInformations()
        {
            Author = string.Empty;
            Note = string.Empty;
            CreditPhoto = string.Empty;
            StateHisto = string.Empty;
        }

        /// <summary>
        /// Inits the document.
        /// </summary>
        private void InitializeDocumentInformations()
        {
            if (CurrentDocument != null)
            {
                Author = CurrentDocument.Author;
                Note = CurrentDocument.Note;
                CreditPhoto = CurrentDocument.PhotoCredit;

                //Init flow historical
                var query = GetDataContext.GetHistoryByUserGroupsMessageFlowQuery(GlobalWebContext.CurrentUser.UserId, CurrentDocument.Identifier, GlobalWebContext.GetIsAdministrator(CurrentFolderType));
                GetDataContext.Load(query, OnHistoryByUserGroupsMessageFlowQuery, null);

                EnabledInformation();
            }
            else if (CurrentVersion != null)
            {
                ClearInformations();
                DisableInformation();
            }
            else
            {
                ClearInformations();
            }
        }

        /// <summary>
        /// Clears the version.
        /// </summary>
        public void ClearVersion()
        {
            InitializeDocumentInformations();
        }

        /// <summary>
        /// Inits the document informations.
        /// </summary>
        private void InitializeVersionInformations()
        {
            if (CurrentVersion != null)
            {
                if (CurrentVersion.IsCurrentVersion)
                {
                    //The document informations is used to fill the data
                    InitializeDocumentInformations();
                }
                else
                {
                    if (CurrentVersion.Author != null) Author = CurrentVersion.Author;
                    if (CurrentVersion.Note != null) Note = CurrentVersion.Note;
                    if (CurrentVersion.PhotoCredit != null) CreditPhoto = CurrentVersion.PhotoCredit;

                    //Init flow historical
                    var query = GetDataContext.GetHistoryByUserGroupsMessageFlowQuery(GlobalWebContext.CurrentUser.UserId, CurrentDocument.Identifier, GlobalWebContext.GetIsAdministrator(CurrentFolderType));
                    GetDataContext.Load(query, OnHistoryByUserGroupsMessageFlowQuery, null);

                    DisableInformation();
                }
            }
        }

        /// <summary>
        /// Must be override in child class
        /// </summary>
        public override sealed void InitLabel()
        {
            base.InitLabel();

            InfoDocLabel = Resx.GetLabel(ResxFolderPage.INFO_DOCUMENT);
            NoteLabel = Resx.GetLabel(ResxInfosDocument.NOTE);
            AuthorLabel = Resx.GetLabel(ResxInfosDocument.AUTHOR);
            CreditPhotoLabel = Resx.GetLabel(ResxInfosDocument.PHOTO_CREDIT);
            StateHistoLabel = Resx.GetLabel(ResxFolderPage.UPDATEDOCUMENT);
            StateHistoLabel = Resx.GetLabel(ResxFolderPage.STATEHISTORY);

            m_sMsgIndexedBy = Resx.GetLabel(ResxFlowStateHistory.MSG_INDEXEDBY);
            m_sMsgValidatedBy = Resx.GetLabel(ResxFlowStateHistory.MSG_VALIDATEDBY);
            m_sMsgTransferedBy = Resx.GetLabel(ResxFlowStateHistory.MSG_TRANSFEREDBY);
            m_sMsgRejectedBy = Resx.GetLabel(ResxFlowStateHistory.MSG_REJECTEDBY);
            m_sMsgReadBy = Resx.GetLabel(ResxFlowStateHistory.MSG_READBY);
            m_sLabelNoHistory = Resx.GetLabel(ResxFlowStateHistory.NOSTATEHISTORY);

            TextBlockToSearch.Text = Resx.GetLabel(ResxCommon.MODIFY);
        }

        /// <summary>
        /// Called when [update information].
        /// </summary>
        private void OnUpdateInformation(object userState)
        {
            RaiseDocumentUpdating();
        }

        /// <summary>
        /// Disables the information.
        /// </summary>
        public void DisableInformation()
        {
            VisualStateManager.GoToState(this, "NoData", false);
        }

        /// <summary>
        /// Enableds the information.
        /// </summary>
        public void EnabledInformation()
        {
            VisualStateManager.GoToState(this, "Default", false);
        }

        /// <summary>
        /// Called when [history by user groups message flow query].
        /// </summary>
        /// <param name="p_oResult">The p_o result.</param>
        private void OnHistoryByUserGroupsMessageFlowQuery(LoadOperation<StateMessageFlow> p_oResult)
        {
            RaiseDataLoaded();

            try
            {
                List<StateMessageFlow> l_oReturnObjects = new List<StateMessageFlow>(p_oResult.Entities);
                if (l_oReturnObjects.Count > 0)
                {
                    StateMessageFlow l_oReturnObject = l_oReturnObjects.First();

                    if (l_oReturnObject.IsValid)
                    {
                        StringBuilder sb = new StringBuilder();
                        StateHistory.Text = string.Empty;

                        foreach (StateMessageFlow l_oStateMsg in l_oReturnObjects)
                        {
                            string l_sUserInfo = l_oStateMsg.FirstName + " " + l_oStateMsg.LastName;
                            long caseSwitch = l_oStateMsg.StateId;
                            switch (caseSwitch)
                            {
                                case (long)StateDoc.Validated:
                                    sb.AppendFormat(m_sMsgValidatedBy, l_oStateMsg.DateAdded, "\r", l_sUserInfo);
                                    sb.Append("\r\r");
                                    break;

                                case (long)StateDoc.Rejected:
                                    sb.AppendFormat(m_sMsgRejectedBy, l_oStateMsg.DateAdded, "\r", l_sUserInfo);
                                    if (l_oStateMsg.Comment != null)
                                    {
                                        sb.Append("\r------------ \r" + l_oStateMsg.Comment + "\r" + "------------ \r\r");
                                    }
                                    else
                                    {
                                        sb.Append("\r\r");
                                    }
                                    break;

                                case (long)StateDoc.Indexed:
                                    sb.AppendFormat(m_sMsgIndexedBy, l_oStateMsg.DateAdded, "\r", l_sUserInfo);
                                    sb.Append("\r\r");
                                    break;

                                case (long)StateDoc.Read:
                                    sb.AppendFormat(m_sMsgReadBy, l_oStateMsg.DateAdded, "\r", l_sUserInfo);
                                    sb.Append("\r\r");
                                    break;

                                case (long)StateDoc.Tranfered:
                                    sb.AppendFormat(m_sMsgTransferedBy, l_oStateMsg.DateAdded, "\r", l_sUserInfo);
                                    if (l_oStateMsg.Comment != null)
                                    {
                                        sb.Append("\r------------ \r" + l_oStateMsg.Comment + "\r" + "------------ \r\r");
                                    }
                                    else
                                    {
                                        sb.Append("\r\r");
                                    }
                                    break;
                            }
                        }

                        StateHistory.Text = sb.ToString();
                    }
                    else
                    {
                        MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, "", MessageBoxButtons.Ok, MessageBoxIcon.Error);
                        L_oMessage.Show();
                    }
                }
                else
                {
                    StateHistory.Text = string.Empty + m_sLabelNoHistory;
                }
            }
            catch (Exception ex)
            {
                MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, "----OnHistoryByGroupMessageFlowQuery: " + ex.Message, MessageBoxButtons.Ok, MessageBoxIcon.Error);
                L_oMessage.Show();
            }
        }

        #endregion

        #region Internal Type

        public class DocumentInformationEventArgs
        :EventArgs
        {
            /// <summary>
            /// Gets or sets the note.
            /// </summary>
            /// <value>The note.</value>
            public string Note { get; private set; }
            /// <summary>
            /// Gets or sets the credit photo.
            /// </summary>
            /// <value>The credit photo.</value>
            public string CreditPhoto { get; private set; }
            /// <summary>
            /// Gets or sets the author.
            /// </summary>
            /// <value>The author.</value>
            public string Author { get; private set; }

            /// <summary>
            /// Initializes a new instance of the <see cref="DocumentInformationEventArgs"/> class.
            /// </summary>
            /// <param name="note">The note.</param>
            /// <param name="author">The author.</param>
            /// <param name="creditPhoto">The credit photo.</param>
            public DocumentInformationEventArgs(string note, string author, string creditPhoto)
            {
                Note = note ?? string.Empty ;
                Author = author ?? string.Empty;
                CreditPhoto = creditPhoto ?? string.Empty;
            }
        }
        #endregion
    }
}